package pers.xiaojun.boot.tenant.core.security;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import pers.xiaojun.boot.common.biz.system.tenant.TenantCommonApi;
import pers.xiaojun.boot.common.constants.GlobalBusinessCodeConstants;
import pers.xiaojun.boot.common.exception.BusinessException;
import pers.xiaojun.boot.common.pojo.CommonResult;
import pers.xiaojun.boot.security.pojo.AuthUserDetails;
import pers.xiaojun.boot.security.util.SecurityUtils;
import pers.xiaojun.boot.tenant.config.properties.TenantProperties;
import pers.xiaojun.boot.tenant.core.context.TenantContextHolder;
import pers.xiaojun.boot.tenant.core.service.TenantCommonService;
import pers.xiaojun.boot.web.config.properties.WebProperties;
import pers.xiaojun.boot.web.core.filter.ApiRequestFilter;
import pers.xiaojun.boot.web.core.util.ServletUtils;
import pers.xiaojun.boot.web.core.util.WebUtils;

import java.io.IOException;

/**
 * Spring Security 租户安全过滤器
 * <p>
 * 作用：校验请求头的租户是否符合缓存中的租户
 *
 * @author xiaojun
 * @since 2025-11-21
 */
public class TenantSecurityFilter extends ApiRequestFilter {


    private final TenantProperties tenantProperties;
    private final TenantCommonService tenantCommonService;

    public TenantSecurityFilter(
            WebProperties webProperties,
            TenantProperties tenantProperties,
            TenantCommonService tenantCommonService
    ) {
        super(webProperties);
        this.tenantProperties = tenantProperties;
        this.tenantCommonService = tenantCommonService;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        Long tenantId = WebUtils.getHeaderAsLong(request, tenantProperties.getTenantHeader());
        String requestURI = request.getRequestURI();
        // 如果未设置租户编号，并且请求URL不在忽略表中，则不通过
        if (tenantId == null) {
            if (!tenantProperties.getIgnoreUrls().contains(requestURI)) {
                ServletUtils.writeJSON(response, CommonResult.error(
                        GlobalBusinessCodeConstants.BAD_REQUEST.getCode(),
                        "未设置租户")
                );
            }
        }
        // 如果不在在忽略列表中，则进行校验
        if (!tenantProperties.getIgnoreUrls().contains(requestURI)) {
            // 校验租户
            try {
                tenantCommonService.validTenantAvailable(tenantId);
            } catch (BusinessException ex) {
                ServletUtils.writeJSON(response, CommonResult.error(ex.getCode(), ex.getMessage()));
                return;
            }
            // 校验租户编号是否匹配
            AuthUserDetails user = SecurityUtils.getUser();
            if (user != null && !tenantId.equals(user.getTenantId())) {
                ServletUtils.writeJSON(response, CommonResult.error(
                        GlobalBusinessCodeConstants.FORBIDDEN.getCode(),
                        "租户不匹配")
                );
                return;
            }
        }
        filterChain.doFilter(request, response);
    }
}
